package cn.chenyumeng.blog.handler;

import cn.chenyumeng.blog.dto.CommonResponse;
import cn.chenyumeng.blog.dto.ResultCode;
import cn.chenyumeng.blog.exception.CustomException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingPathVariableException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.ServletRequestBindingException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.NoHandlerFoundException;

import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 全局404/500异常捕捉处理
 *
 * @program: blog->GlobalExceptionHandler
 * @description: 全局404/500异常捕捉处理
 * @author: cg
 * @create: 2020-07-17 22:22
 **/
@RestControllerAdvice
public class GlobalExceptionHandler {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    /**
     * 全局异常
     *
     * @param request
     * @param e
     * @return
     */
    @ExceptionHandler(Exception.class)
    public CommonResponse defaultErrorHandler(HttpServletRequest request, Exception e) {
        logger.error("Request URL : {}, Exception : {}", request.getRequestURL(), e.getMessage());
        return CommonResponse.build(ResultCode.SYS_ERROR, e);
    }

    /**
     * 统一处理参数校验异常
     *
     * @param request
     * @param e
     * @return
     */
    @ExceptionHandler({ConstraintViolationException.class,
            MethodArgumentNotValidException.class,
            ServletRequestBindingException.class,
            BindException.class})
    public CommonResponse<?> handleValidationException(HttpServletRequest request, Exception e) {
        List list = new ArrayList();
        if (e instanceof MethodArgumentNotValidException) {
            MethodArgumentNotValidException t = (MethodArgumentNotValidException) e;
            list = t.getBindingResult().getAllErrors().stream()
                    .map(DefaultMessageSourceResolvable::getDefaultMessage)
                    .collect(Collectors.toList());
        } else if (e instanceof BindException) {
            BindException t = (BindException) e;
            list = t.getBindingResult().getAllErrors().stream()
                    .map(DefaultMessageSourceResolvable::getDefaultMessage)
                    .collect(Collectors.toList());
        } else if (e instanceof ConstraintViolationException) {
            ConstraintViolationException t = (ConstraintViolationException) e;
            list = t.getConstraintViolations().stream()
                    .map(ConstraintViolation::getMessage)
                    .collect(Collectors.toList());
        } else if (e instanceof MissingServletRequestParameterException) {
            MissingServletRequestParameterException t = (MissingServletRequestParameterException) e;
            list.add(t.getParameterName() + " 不能为空");
        } else if (e instanceof MissingPathVariableException) {
            MissingPathVariableException t = (MissingPathVariableException) e;
            list.add(t.getVariableName() + " 不能为空");
        } else {
            list.add("必填参数缺失");
        }
        logger.error("\"Request URL : {}, Exception : {}", request.getRequestURL(), list);
        return CommonResponse.build(ResultCode.PARAM_TYPE_BIND_ERROR, list);
    }

    /**
     * 404异常
     *
     * @param request
     * @param e
     * @return
     */
    @ExceptionHandler(NoHandlerFoundException.class)
    public CommonResponse handlerNoFoundException(HttpServletRequest request, Exception e) {
        logger.error("Request URL : {}, Exception : {}", request.getRequestURL(), e.getMessage());
        return CommonResponse.build(ResultCode.NOT_FOUND, "路径不存在，请检查路径是否正确");
    }

    /**
     * 自定义异常
     *
     * @param request
     * @param e
     * @return
     */
    @ExceptionHandler(CustomException.class)
    public CommonResponse loginHandler(HttpServletRequest request, Exception e) {
        logger.error("Request URL : {}, Exception : {}", request.getRequestURL(), e.getMessage());
        return CommonResponse.build(ResultCode.USER_NOT_LOGGED_IN, e);
    }

    /**
     * 空指针异常
     *
     * @param request
     * @param e
     * @return
     */
    @ExceptionHandler(NullPointerException.class)
    public CommonResponse NullPointerExceptionHandler(HttpServletRequest request, Exception e) {
        logger.error("Request URL : {}, Exception : {}", request.getRequestURL(), e.getMessage());
        return CommonResponse.build(ResultCode.PARAM_IS_INVALID, e);
    }

}
